package cn.lycode.system.service.impl;

import cn.lycode.common.core.domain.entity.SysRole;
import cn.lycode.common.core.domain.model.ConditionDTO;
import cn.lycode.common.core.domain.model.SelectIdsDTO;
import cn.lycode.common.core.page.PageResult;
import cn.lycode.common.core.page.PageUtil;
import cn.lycode.common.event.EventPublisher;
import cn.lycode.common.event.SessionChangeEvent;
import cn.lycode.common.event.SessionChangeMeta;
import cn.lycode.common.exception.ServiceException;
import cn.lycode.common.utils.SecurityUtils;
import cn.lycode.common.utils.StringUtils;
import cn.lycode.system.domain.dto.ChangeStatusDTO;
import cn.lycode.system.domain.dto.sysrole.SysRoleAddDTO;
import cn.lycode.system.domain.dto.sysrole.SysRoleMenuDTO;
import cn.lycode.system.domain.dto.sysrole.SysRoleUpDTO;
import cn.lycode.system.domain.vo.MenuTreeVO;
import cn.lycode.system.domain.vo.SysRoleMenuVO;
import cn.lycode.system.mapper.SysRoleMapper;
import cn.lycode.system.mapper.SysRoleMenuMapper;
import cn.lycode.system.mapper.SysUserRoleMapper;
import cn.lycode.system.service.SysMenuService;
import cn.lycode.system.service.SysRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @Title: SysRoleServiceImpl
 * @Author lyg
 * @Date 2024/7/16 15:41
 * @description: 系统角色
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl implements SysRoleService {
    private final SysRoleMapper roleMapper;
    private final SysUserRoleMapper userRoleMapper;
    private final SysRoleMenuMapper roleMenuMapper;
    private final SysMenuService sysMenuService;
    private final EventPublisher eventPublisher;

    @Override
    public Set<String> selectRoleNameListByUserId(Long userId) {
        return new HashSet<>(roleMapper.selectRoleNameListByUserId(userId));
    }



    @Override
    public List<SysRole> selectRoleAll() {
        return roleMapper.selectRoleList(new ConditionDTO());
    }


    @Override
    public PageResult<SysRole> list(ConditionDTO dto) {
        PageUtil.startPage(dto);
        List<SysRole> sysRoles = roleMapper.selectRoleList(dto);
        return PageUtil.getPageResult(sysRoles);
    }


    @Override
    public boolean hasExistsRoleName(String roleName, Long roleId) {
        int ret = roleMapper.countRoleName(roleName, roleId);
        return ret > 0;
    }

    @Override
    public int insertRole(SysRoleAddDTO dto) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(dto, role);
        role.setCreateTime(new Date());
        role.setCreateBy(SecurityUtils.getLoginUsername());
        return roleMapper.insertRole(role);
    }

    @Override
    public void checkRoleAllowed(Long roleId) {
        if (SecurityUtils.isSuperAdminRole(roleId)) {
            throw new ServiceException("禁止修改超级管理员！");
        }
    }

    @Transactional
    @Override
    public boolean changeRoleStatus(ChangeStatusDTO dto) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(dto, role);
        role.setUpdateBy(SecurityUtils.getLoginUsername());
        role.setUpdateTime(new Date());
        roleMapper.updateRole(role);
        // 获取到影响范围的roleFlag
        String roleFlag = roleMapper.selectRoleNameById(role.getId());
        eventPublisher.publish(new SessionChangeEvent(this, SessionChangeMeta.role(roleFlag)));
        return true;
    }

    @Override
    public int update(SysRoleUpDTO dto) {
        SysRole role = new SysRole();
        BeanUtils.copyProperties(dto, role);
        role.setUpdateBy(SecurityUtils.getLoginUsername());
        role.setUpdateTime(new Date());
        return roleMapper.updateRole(role);
    }

    /**
     * 获取角色拥有的菜单ids已经全部菜单树
     */
    @Override
    public SysRoleMenuVO queryRoleMenu(Long roleId) {
        //查询全部菜单树
        List<MenuTreeVO> menuTreeVOS = sysMenuService.queryRoleMenuTree();
        //查询角色拥有的菜单ID
        List<Long> selectIds = roleMenuMapper.selectMenuIdListByRoleId(roleId);
        SysRoleMenuVO menuVO = new SysRoleMenuVO();
        menuVO.setMenuLists(menuTreeVOS);
        menuVO.setSelectIds(selectIds);
        return menuVO;
    }

    @Override
    public void setRoleMenus(SysRoleMenuDTO dto) {
        // 删除当前角色下的所有关联菜单记录
        roleMenuMapper.deleteRoleMenuByRoleId(dto.getRoleId());
        //插入更新的角色下关联菜单记录
        if (StringUtils.isNotNull(dto.getMenuIds())) {
           roleMenuMapper.batchRoleMenu(dto.getRoleId(), dto.getMenuIds());
        }

        // 获取到影响范围的roleFlag
        String roleFlag = roleMapper.selectRoleNameById(dto.getRoleId());
        eventPublisher.publish(new SessionChangeEvent(this, SessionChangeMeta.role(roleFlag)));
    }

    /**
     * 批量删除角色
     */
    @Transactional
    @Override
    public int remove(SelectIdsDTO dto) {
        //已经被分配的角色不能删除
        for (Long roleId : dto.getIds()) {
            checkRoleAllowed(roleId); //超级管理员不允许被删除！
            //TODO 校验用户是否有此角色数据操作权限
//            checkRoleDataScope(roleId);
            if (countUserRoleByRoleId(roleId) > 0) {
                throw new ServiceException("角色已被分配,禁止删除");
            }
        }
        // 删除角色与菜单关联
        roleMenuMapper.deleteRoleMenuByRoleIds(dto.getIds());
        //TODO 删除角色和部门关联（自定义部门数据权限）
        //删除角色
        return roleMapper.deleteRoleByIds(dto.getIds());
    }

    /**
     * 通过角色ID查询角色使用数量
     *
     * @param roleId 角色ID
     * @return 结果
     */
    @Override
    public int countUserRoleByRoleId(Long roleId) {
        return userRoleMapper.countUserRoleByRoleId(roleId);
    }


}
